Commit d597b3ce by Dodji Seketeli Committed by Dodji Seketeli

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
parent 210879b8
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> 2009-01-21 Bingfeng Mei <bmei@broadcom.com>
* alias.c (walk_mems_1, walk_mems_2, insn_alias_sets_conflict_p): * alias.c (walk_mems_1, walk_mems_2, insn_alias_sets_conflict_p):
......
...@@ -8363,4 +8363,73 @@ warn_for_sign_compare (location_t location, ...@@ -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" #include "gt-c-common.h"
...@@ -1971,67 +1971,6 @@ warn_if_shadowing (tree new_decl) ...@@ -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. /* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same Check for errors (such as an incompatible declaration for the same
name already seen in the same scope). name already seen in the same scope).
...@@ -2254,7 +2193,7 @@ pushdecl (tree x) ...@@ -2254,7 +2193,7 @@ pushdecl (tree x)
skip_external_and_shadow_checks: skip_external_and_shadow_checks:
if (TREE_CODE (x) == TYPE_DECL) if (TREE_CODE (x) == TYPE_DECL)
clone_underlying_type (x); set_underlying_type (x);
bind (name, x, scope, /*invisible=*/false, nested); bind (name, x, scope, /*invisible=*/false, nested);
......
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> 2009-01-19 Jason Merrill <jason@redhat.com>
PR c++/23287 PR c++/23287
......
...@@ -3179,6 +3179,14 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -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 \ && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE)) && !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. */ /* Nonzero if NODE which declares a type. */
#define DECL_DECLARES_TYPE_P(NODE) \ #define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_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); ...@@ -4539,6 +4547,7 @@ extern tree check_explicit_specialization (tree, tree, int, int);
extern tree make_auto (void); extern tree make_auto (void);
extern tree do_auto_deduction (tree, tree, tree); extern tree do_auto_deduction (tree, tree, tree);
extern tree type_uses_auto (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 tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree); extern bool is_auto (const_tree);
extern tree process_template_parm (tree, tree, bool, bool); extern tree process_template_parm (tree, tree, bool, bool);
......
...@@ -8729,6 +8729,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8729,6 +8729,7 @@ grokdeclarator (const cp_declarator *declarator,
decl = build_lang_decl (TYPE_DECL, unqualified_id, type); decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else else
decl = build_decl (TYPE_DECL, unqualified_id, type); decl = build_decl (TYPE_DECL, unqualified_id, type);
if (id_declarator && declarator->u.id.qualifying_scope) { if (id_declarator && declarator->u.id.qualifying_scope) {
error ("%Jtypedef name may not be a nested-name-specifier", decl); error ("%Jtypedef name may not be a nested-name-specifier", decl);
TREE_TYPE (decl) = error_mark_node; TREE_TYPE (decl) = error_mark_node;
...@@ -8763,12 +8764,11 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8763,12 +8764,11 @@ grokdeclarator (const cp_declarator *declarator,
&& TYPE_ANONYMOUS_P (type) && TYPE_ANONYMOUS_P (type)
&& cp_type_quals (type) == TYPE_UNQUALIFIED) && cp_type_quals (type) == TYPE_UNQUALIFIED)
{ {
tree oldname = TYPE_NAME (type);
tree t; tree t;
/* Replace the anonymous name with the real name everywhere. */ /* Replace the anonymous name with the real name everywhere. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) 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; TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type)) if (TYPE_LANG_SPECIFIC (type))
......
...@@ -804,6 +804,9 @@ grokfield (const cp_declarator *declarator, ...@@ -804,6 +804,9 @@ grokfield (const cp_declarator *declarator,
DECL_NONLOCAL (value) = 1; DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type; DECL_CONTEXT (value) = current_class_type;
if (declspecs->specs[(int)ds_typedef])
set_underlying_type (value);
if (processing_template_decl) if (processing_template_decl)
value = push_template_decl (value); value = push_template_decl (value);
...@@ -1125,19 +1128,6 @@ save_template_attributes (tree *attr_p, tree *decl_p) ...@@ -1125,19 +1128,6 @@ save_template_attributes (tree *attr_p, tree *decl_p)
if (!late_attrs) if (!late_attrs)
return; 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)) if (DECL_P (*decl_p))
q = &DECL_ATTRIBUTES (*decl_p); q = &DECL_ATTRIBUTES (*decl_p);
else else
......
...@@ -847,28 +847,20 @@ pushdecl_maybe_friend (tree x, bool is_friend) ...@@ -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 /* 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 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) if (TREE_CODE (x) == TYPE_DECL)
{ {
tree type = TREE_TYPE (x); tree type = TREE_TYPE (x);
if (DECL_IS_BUILTIN (x))
{ if (DECL_IS_BUILTIN (x)
if (TYPE_NAME (type) == 0) || (TREE_TYPE (x) != error_mark_node
TYPE_NAME (type) = x; && TYPE_NAME (type) != x
} /* We don't want to copy the type when all we're
else if (type != error_mark_node && TYPE_NAME (type) != x doing is making a TYPE_DECL for the purposes of
/* We don't want to copy the type when all we're inlining. */
doing is making a TYPE_DECL for the purposes of && (!TYPE_NAME (type)
inlining. */ || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
&& (!TYPE_NAME (type) set_underlying_type (x);
|| 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 (type != error_mark_node if (type != error_mark_node
&& TYPE_NAME (type) && TYPE_NAME (type)
......
...@@ -7387,6 +7387,31 @@ instantiate_class_template (tree type) ...@@ -7387,6 +7387,31 @@ instantiate_class_template (tree type)
&& DECL_TEMPLATE_INFO (t)) && DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (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_nested_class ();
pop_from_top_level (); pop_from_top_level ();
pop_deferring_access_checks (); pop_deferring_access_checks ();
...@@ -11869,6 +11894,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) ...@@ -11869,6 +11894,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
tree fndecl; tree fndecl;
tree gen_tmpl; tree gen_tmpl;
tree spec; tree spec;
tree t;
HOST_WIDE_INT saved_processing_template_decl; HOST_WIDE_INT saved_processing_template_decl;
if (tmpl == error_mark_node) if (tmpl == error_mark_node)
...@@ -11947,6 +11973,24 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) ...@@ -11947,6 +11973,24 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
/* Now we know the specialization, compute access previously /* Now we know the specialization, compute access previously
deferred. */ deferred. */
push_access_scope (fndecl); 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 (); perform_deferred_access_checks ();
pop_access_scope (fndecl); pop_access_scope (fndecl);
pop_deferring_access_checks (); pop_deferring_access_checks ();
...@@ -16633,7 +16677,15 @@ resolve_typename_type (tree type, bool only_current_p) ...@@ -16633,7 +16677,15 @@ resolve_typename_type (tree type, bool only_current_p)
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE); gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (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 /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
it first before we can figure out what NAME refers to. */ it first before we can figure out what NAME refers to. */
...@@ -16958,4 +17010,45 @@ type_uses_auto (tree type) ...@@ -16958,4 +17010,45 @@ type_uses_auto (tree type)
return NULL_TREE; 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" #include "gt-cp-pt.h"
...@@ -1529,6 +1529,30 @@ check_accessibility_of_qualified_id (tree decl, ...@@ -1529,6 +1529,30 @@ check_accessibility_of_qualified_id (tree decl,
tree scope; tree scope;
tree qualifying_type = NULL_TREE; 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 we're not checking, return immediately. */
if (deferred_access_no_check) if (deferred_access_no_check)
return; return;
......
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> 2009-01-21 Daniel Kraft <d@domob.eu>
PR fortran/38887 PR fortran/38887
......
...@@ -17,8 +17,8 @@ template <> struct X::Y<int> { ...@@ -17,8 +17,8 @@ template <> struct X::Y<int> {
A::X x; // { dg-error "this context" } 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" } 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" }
// PR c++/24671 // PR c++/24671
// { dg-options "" } // { dg-do compile }
template<typename> struct A template<typename> struct A
{ {
...@@ -9,9 +9,9 @@ template<typename> struct A ...@@ -9,9 +9,9 @@ template<typename> struct A
template<typename> struct B template<typename> struct B
{ {
B(const B&); // { dg-message "candidate" } B(const B&);
typedef typename A<char[A<B>::i]>::X Y; typedef typename A<char[A<B>::i]>::X Y; // { dg-error "forbids zero-size array" }
template<typename T> B(T, Y); // { dg-error "call" } template<typename T> B(T, Y);
}; };
B<int> b(0,0); B<int> b(0,0); // { dg-message "instantiated from here" }
// 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" }
// 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;
// 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" }
// 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);
}
};
...@@ -5,14 +5,14 @@ template < class T > class A ...@@ -5,14 +5,14 @@ template < class T > class A
public: public:
typedef typename T::myT anotherT; // { dg-error "" } undefined type typedef typename T::myT anotherT; // { dg-error "" } undefined type
anotherT t; // { dg-error "" } undefined type anotherT t;
A() { } A() { }
A(anotherT _t) { // { dg-error "" } undefined type A(anotherT _t) {
t=_t; t=_t;
} }
anotherT getT() { // { dg-error "" } undefined type anotherT getT() {
return t; return t;
} }
}; };
......
...@@ -3412,6 +3412,9 @@ struct tree_target_option GTY(()) ...@@ -3412,6 +3412,9 @@ struct tree_target_option GTY(())
/* Return a tree node that encapsulates the current target options. */ /* Return a tree node that encapsulates the current target options. */
extern tree build_target_option_node (void); 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. /* Define the overall contents of a tree node.
It may be any of the structures declared above It may be any of the structures declared above
......
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> 2009-01-20 Benjamin Kosnik <bkoz@redhat.com>
Uros Bizjak <ubizjak@gmail.com> Uros Bizjak <ubizjak@gmail.com>
......
...@@ -549,11 +549,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) ...@@ -549,11 +549,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
*/ */
class free_list class free_list
{ {
public:
typedef size_t* value_type; typedef size_t* value_type;
typedef __detail::__mini_vector<value_type> vector_type; typedef __detail::__mini_vector<value_type> vector_type;
typedef vector_type::iterator iterator; typedef vector_type::iterator iterator;
typedef __mutex __mutex_type; typedef __mutex __mutex_type;
private:
struct _LT_pointer_compare struct _LT_pointer_compare
{ {
bool bool
......
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