re PR c++/26693 (Access checks not performed for types in templates)

gcc/ChangeLog:
2009-01-21  Dodji Seketeli  <dodji@redhat.com>

	PR c++/26693
	* c-decl.c: (clone_underlying_type): Move this  ...
	* c-common.c (set_underlying_type): ... here.
	Also, make sure the function  properly sets TYPE_STUB_DECL() on
	the newly created typedef variant type.
	(is_typedef_decl ): New entry point.
	* tree.h: Added a new member member_types_needing_access_check to
	struct tree_decl_non_common.
	(set_underlying_type): New entry point.
	(is_typedef_type): Likewise.

gcc/cp/ChangeLog/
2009-01-21  Dodji Seketeli  <dodji@redhat.com>

	PR c++/26693
	* decl2.c (grokfield): when a typedef appears in a
	class, create the typedef variant type node for it.
	(save_template_attributes): Creating typedef variant type node
	 here is now useless.
	* decl.c (grokdeclarator): If the typedef'ed struct/class was
	anonymous, set the proper type name to all its type variants.
	* name-lookup.c (pushdecl_maybe_friend): Reuse the
	set_underlying_type function to install typedef variant types.
	* cp-tree.h (MEMBER_TYPES_NEEDING_ACCESS_CHECK): New template accessor
	macro.
	(append_type_to_template_for_access_check): New entry points.
	* semantics.c (check_accessibility_of_qualified_id):
	When a typedef that is a member of a class appears in a template,
	add it to the template. It will be ...
	* pt.c (instantiate_class_template, instantiate_template ): ... access
	checked at template instantiation time.
	(tsubst): Handle the case of being called with NULL args.
	(resolve_type_name_type): The type name should be the name of the
	main type variant.
	(append_type_to_template_for_access_check): New entry point.

gcc/testsuite/ChangeLog
2009-01-21  Dodji Seketeli  <dodji@redhat.com>

	PR c++/26693
	* g++.dg/template/typedef11.C: New test.
	* g++.dg/template/typedef12.C: Likewise.
	* g++.dg/template/typedef13.C: Likewise.
	* g++.dg/template/typedef14.C: Likewise.
	* g++.dg/template/sfinae3.C: Compile this pedantically.
	The only errors expected should be the one saying the typedef is ill
	formed.
	* g++.old-deja/g++.pt/typename8.C: Likewise.
	* g++.dg/template/access11.C: Update this.

libstdc++-v3/ChangeLog:
2009-01-21  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++.

From-SVN: r143546
This commit is contained in:
Dodji Seketeli 2009-01-21 16:14:49 +00:00 committed by Dodji Seketeli
parent 210879b85b
commit d597b3ce68
21 changed files with 364 additions and 107 deletions

View File

@ -1,3 +1,16 @@
2009-01-21 Dodji Seketeli <dodji@redhat.com>
PR c++/26693
* c-decl.c: (clone_underlying_type): Move this ...
* c-common.c (set_underlying_type): ... here.
Also, make sure the function properly sets TYPE_STUB_DECL() on
the newly created typedef variant type.
(is_typedef_decl ): New entry point.
* tree.h: Added a new member member_types_needing_access_check to
struct tree_decl_non_common.
(set_underlying_type): New entry point.
(is_typedef_type): Likewise.
2009-01-21 Bingfeng Mei <bmei@broadcom.com>
* alias.c (walk_mems_1, walk_mems_2, insn_alias_sets_conflict_p):

View File

@ -8363,4 +8363,73 @@ warn_for_sign_compare (location_t location,
}
}
/* 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
set_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_STUB_DECL (tt) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
TYPE_NAME (tt) = x;
TREE_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt;
}
}
/* Returns true if X is a typedef type. */
bool
is_typedef_decl (tree x)
{
return (x && TREE_CODE (x) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (x) != NULL_TREE);
}
#include "gt-c-common.h"

View File

@ -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).
@ -2254,7 +2193,7 @@ pushdecl (tree x)
skip_external_and_shadow_checks:
if (TREE_CODE (x) == TYPE_DECL)
clone_underlying_type (x);
set_underlying_type (x);
bind (name, x, scope, /*invisible=*/false, nested);

View File

@ -1,3 +1,27 @@
2009-01-21 Dodji Seketeli <dodji@redhat.com>
PR c++/26693
* decl2.c (grokfield): when a typedef appears in a
class, create the typedef variant type node for it.
(save_template_attributes): Creating typedef variant type node
here is now useless.
* decl.c (grokdeclarator): If the typedef'ed struct/class was
anonymous, set the proper type name to all its type variants.
* name-lookup.c (pushdecl_maybe_friend): Reuse the
set_underlying_type function to install typedef variant types.
* cp-tree.h (MEMBER_TYPES_NEEDING_ACCESS_CHECK): New template accessor
macro.
(append_type_to_template_for_access_check): New entry points.
* semantics.c (check_accessibility_of_qualified_id):
When a typedef that is a member of a class appears in a template,
add it to the template. It will be ...
* pt.c (instantiate_class_template, instantiate_template ): ... access
checked at template instantiation time.
(tsubst): Handle the case of being called with NULL args.
(resolve_type_name_type): The type name should be the name of the
main type variant.
(append_type_to_template_for_access_check): New entry point.
2009-01-19 Jason Merrill <jason@redhat.com>
PR c++/23287

View File

@ -3179,6 +3179,14 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE))
/* The chained list of some types that are referenced in templates.
These types are those which need to be access checked at
template instantiation time. For the time being, only typedef-ed types defined
as class members are put here at parsing time.
Other types for which access check could be required at template instantiation
time could be added later. */
#define MEMBER_TYPES_NEEDING_ACCESS_CHECK(NODE) DECL_ACCESS (NODE)
/* Nonzero if NODE which declares a type. */
#define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
@ -4539,6 +4547,7 @@ extern tree check_explicit_specialization (tree, tree, int, int);
extern tree make_auto (void);
extern tree do_auto_deduction (tree, tree, tree);
extern tree type_uses_auto (tree);
extern void append_type_to_template_for_access_check (tree, tree, tree);
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
extern tree process_template_parm (tree, tree, bool, bool);

View File

@ -8729,6 +8729,7 @@ grokdeclarator (const cp_declarator *declarator,
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
decl = build_decl (TYPE_DECL, unqualified_id, 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;
@ -8763,12 +8764,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))

View File

@ -804,6 +804,9 @@ grokfield (const cp_declarator *declarator,
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
if (declspecs->specs[(int)ds_typedef])
set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);
@ -1125,19 +1128,6 @@ save_template_attributes (tree *attr_p, tree *decl_p)
if (!late_attrs)
return;
/* Give this type a name so we know to look it up again at instantiation
time. */
if (TREE_CODE (*decl_p) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
{
tree oldt = TREE_TYPE (*decl_p);
tree newt = build_variant_type_copy (oldt);
DECL_ORIGINAL_TYPE (*decl_p) = oldt;
TREE_TYPE (*decl_p) = newt;
TYPE_NAME (newt) = *decl_p;
TREE_USED (newt) = TREE_USED (*decl_p);
}
if (DECL_P (*decl_p))
q = &DECL_ATTRIBUTES (*decl_p);
else

View File

@ -847,28 +847,20 @@ pushdecl_maybe_friend (tree x, bool is_friend)
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
name. See the extensive comment in ../c-decl.c (pushdecl). */
name. See the extensive comment of set_underlying_type (). */
if (TREE_CODE (x) == TYPE_DECL)
{
tree type = TREE_TYPE (x);
if (DECL_IS_BUILTIN (x))
{
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = x;
}
else if (type != error_mark_node && TYPE_NAME (type) != x
/* We don't want to copy the type when all we're
doing is making a TYPE_DECL for the purposes of
inlining. */
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
{
DECL_ORIGINAL_TYPE (x) = type;
type = build_variant_type_copy (type);
TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
TYPE_NAME (type) = x;
TREE_TYPE (x) = type;
}
if (DECL_IS_BUILTIN (x)
|| (TREE_TYPE (x) != error_mark_node
&& TYPE_NAME (type) != x
/* We don't want to copy the type when all we're
doing is making a TYPE_DECL for the purposes of
inlining. */
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
set_underlying_type (x);
if (type != error_mark_node
&& TYPE_NAME (type)

View File

@ -7387,6 +7387,31 @@ instantiate_class_template (tree type)
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
/* Some types referenced from within the template code need to be access
checked at template instantiation time, i.e now. These types were
added to the template at parsing time. Let's get those and perfom
the acces checks then. */
for (t = MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ); t; t = TREE_CHAIN (t))
{
tree type_decl = TREE_PURPOSE (t);
tree type_scope = TREE_VALUE (t);
if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
continue;
if (uses_template_parms (type_decl))
type_decl = tsubst (type_decl, args, tf_error, NULL_TREE);
if (uses_template_parms (type_scope))
type_scope = tsubst (type_scope, args, tf_error, NULL_TREE);
gcc_assert (type_decl && type_decl != error_mark_node
&& type_scope && type_scope != error_mark_node);
perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl);
}
perform_deferred_access_checks ();
pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
@ -11869,6 +11894,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
tree fndecl;
tree gen_tmpl;
tree spec;
tree t;
HOST_WIDE_INT saved_processing_template_decl;
if (tmpl == error_mark_node)
@ -11947,6 +11973,24 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
/* Now we know the specialization, compute access previously
deferred. */
push_access_scope (fndecl);
/* Some types referenced from within the template code need to be access
checked at template instantiation time, i.e now. These types were
added to the template at parsing time. Let's get those and perfom
the acces checks then. */
for (t = MEMBER_TYPES_NEEDING_ACCESS_CHECK (tmpl); t; t = TREE_CHAIN (t))
{
tree type_decl = TREE_PURPOSE (t);
tree type_scope = TREE_VALUE (t);
if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
continue;
if (uses_template_parms (type_decl))
type_decl = tsubst (type_decl, targ_ptr, tf_error, NULL_TREE);
perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl);
}
perform_deferred_access_checks ();
pop_access_scope (fndecl);
pop_deferring_access_checks ();
@ -16633,7 +16677,15 @@ resolve_typename_type (tree type, bool only_current_p)
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
name = TYPE_IDENTIFIER (type);
/* Usually the non-qualified identifier of a TYPENAME_TYPE is
TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
the typedef. In that case TYPE_IDENTIFIER (type) is not the non-qualified
identifier of the TYPENAME_TYPE anymore.
So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
TYPENAME_TYPE instead, we avoid messing up with a possible
typedef variant case. */
name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
/* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
it first before we can figure out what NAME refers to. */
@ -16958,4 +17010,45 @@ type_uses_auto (tree type)
return NULL_TREE;
}
/* Append TYPE_DECL to the template TMPL.
TMPL is eiter a class type or a FUNCTION_DECL associated
to a TEMPLATE_DECL.
At TMPL instanciation time, TYPE_DECL will be checked to see
if it can be accessed through SCOPE. */
void
append_type_to_template_for_access_check (tree templ,
tree type_decl,
tree scope)
{
tree node, templ_decl;
gcc_assert (templ
&& get_template_info (templ)
&& TI_TEMPLATE (get_template_info (templ))
&& type_decl
&& (TREE_CODE (type_decl) == TYPE_DECL));
templ_decl = TI_TEMPLATE (get_template_info (templ));
gcc_assert (templ_decl);
/* Make sure we don't append the type to the template twice.
If this appears to be too slow, the
MEMBER_TYPE_NEEDING_ACCESS_CHECK property
of templ should be a hash table instead. */
for (node = MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl);
node;
node = TREE_CHAIN (node))
{
tree decl = TREE_PURPOSE (node);
tree type_scope = TREE_VALUE (node);
if (decl == type_decl && type_scope == scope)
return;
}
MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl) =
tree_cons (type_decl, scope,
MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl));
}
#include "gt-cp-pt.h"

View File

@ -1529,6 +1529,30 @@ check_accessibility_of_qualified_id (tree decl,
tree scope;
tree qualifying_type = NULL_TREE;
/* If we are parsing a template declaration and if decl is a typedef,
add it to a list tied to the template.
At template instantiation time, that list will be walked and
access check performed. */
if (is_typedef_decl (decl))
{
/* This the scope through which type_decl is accessed.
It will be useful information later to do access check for
type_decl usage. */
tree scope = nested_name_specifier ? nested_name_specifier : DECL_CONTEXT (decl);
tree templ_info = NULL;
tree cs = current_scope ();
if (cs && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL))
templ_info = get_template_info (cs);
if (templ_info
&& TI_TEMPLATE (templ_info)
&& scope
&& CLASS_TYPE_P (scope)
&& !currently_open_class (scope))
append_type_to_template_for_access_check (current_scope (), decl, scope);
}
/* If we're not checking, return immediately. */
if (deferred_access_no_check)
return;

View File

@ -1,3 +1,16 @@
2009-01-21 Dodji Seketeli <dodji@redhat.com>
PR c++/26693
* g++.dg/template/typedef11.C: New test.
* g++.dg/template/typedef12.C: Likewise.
* g++.dg/template/typedef13.C: Likewise.
* g++.dg/template/typedef14.C: Likewise.
* g++.dg/template/sfinae3.C: Compile this pedantically.
The only errors expected should be the one saying the typedef is ill
formed.
* g++.old-deja/g++.pt/typename8.C: Likewise.
* g++.dg/template/access11.C: Update this.
2009-01-21 Daniel Kraft <d@domob.eu>
PR fortran/38887

View File

@ -17,8 +17,8 @@ template <> struct X::Y<int> {
A::X x; // { dg-error "this context" }
};
template <typename T> struct X::Y {
template <typename T> struct X::Y { // { dg-error "this context" }
typename T::X x; // { dg-error "this context" }
};
template struct X::Y<A>; // { dg-message "instantiated" }
template struct X::Y<A>; // { dg-message "instantiated from here" }

View File

@ -1,5 +1,5 @@
// PR c++/24671
// { dg-options "" }
// { dg-do compile }
template<typename> struct A
{
@ -9,9 +9,9 @@ template<typename> struct A
template<typename> struct B
{
B(const B&); // { dg-message "candidate" }
typedef typename A<char[A<B>::i]>::X Y;
template<typename T> B(T, Y); // { dg-error "call" }
B(const B&);
typedef typename A<char[A<B>::i]>::X Y; // { dg-error "forbids zero-size array" }
template<typename T> B(T, Y);
};
B<int> b(0,0);
B<int> b(0,0); // { dg-message "instantiated from here" }

View File

@ -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;
return Alpha::X ();
}
int i = bar<0> (); // { dg-error "within this context" }

View File

@ -0,0 +1,23 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: Jason Merrill <jason@redhat.com>, PR c++/26693
// { dg-do compile }
class A
{
protected:
typedef int mytype;
};
template <class T> class B;
class C: public A
{
template <class T> friend class B;
};
template <class T> class B
{
C::mytype mem;
};
B<int> b;

View File

@ -0,0 +1,16 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/26693
// { dg-do compile }
class A
{
typedef int mytype; // { dg-error "typedef int A::mytype' is private" }
};
template <class T> class B : public A
{ // { dg-error "within this context" }
mytype mem;
};
B<int> b; // { dg-message "instantiated from here" }

View File

@ -0,0 +1,16 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/26693
// { dg-do compile }
template <class T>
struct A
{
typedef int mytype;
void
foo ()
{
mytype v = ~static_cast<mytype> (0);
}
};

View File

@ -5,14 +5,14 @@ template < class T > class A
public:
typedef typename T::myT anotherT; // { dg-error "" } undefined type
anotherT t; // { dg-error "" } undefined type
anotherT t;
A() { }
A(anotherT _t) { // { dg-error "" } undefined type
A(anotherT _t) {
t=_t;
}
anotherT getT() { // { dg-error "" } undefined type
anotherT getT() {
return t;
}
};

View File

@ -3412,6 +3412,9 @@ struct tree_target_option GTY(())
/* Return a tree node that encapsulates the current target options. */
extern tree build_target_option_node (void);
extern void set_underlying_type (tree x);
extern bool is_typedef_decl (tree x);
/* Define the overall contents of a tree node.
It may be any of the structures declared above

View File

@ -1,3 +1,9 @@
2009-01-21 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++.
2009-01-20 Benjamin Kosnik <bkoz@redhat.com>
Uros Bizjak <ubizjak@gmail.com>

View File

@ -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